//David Wasser
//May 6, 2009
//Software Design, Period 6
//Ultimate Frisbee

/* ThrowingRoutine is a MovementRoutine given to computer players when they
 * have the Disc to coordinate throwing and then return to the old 
 * MovementRoutine.
 */

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.vecmath.Point3d;
import javax.vecmath.Tuple3d;
import javax.vecmath.Vector3d;
public class ThrowingRoutine implements MovementRoutine{
	Player player;
	Disc disc;
	Field field;
	Vector3d vec;
	MovementRoutine oldRoutine;
	HashSet<Player> players;
	HashSet<Player> catchPlayers;
	Object[] test;
	Object[] catcher;
	Iterator<Player> it;
	Player temp;
	double k;
	
	/** Creates the ThrowingRoutine for the specified Player, with the input Disc
	 ** and MovementRoutine to return to afterwards.
	 **/
	public ThrowingRoutine(Player player, Disc disc, MovementRoutine routine){
		this.player = player;
		this.disc = disc;
		oldRoutine = routine;
		players = new HashSet<Player>();
		players.addAll(player.team.getPlayers());
		players.addAll(player.team.getOtherTeam().getPlayers());
	}//End ThrowingRoutine()
	
	/** Determines if there are any throws that would get to a Player and if there
	 ** are multiple, goes through with the thorw that would gain the most yards.
	 **/
	public Tuple3d[] step(){
		if(player.team.strat.starting){
			disc.velocity = new Vector3d(14*Math.cos(Math.PI/15)*(player.team.endZone == Team.RIGHT?1:-1), 0, 14*Math.cos(Math.PI/15));
			((DiscMechanics)(disc.routine)).startThrow(0, Math.PI/15);
			return new Tuple3d[] {player.position, new Vector3d((player.team.endZone == Team.RIGHT)?1:-1,0,0)};
		}//End if
		vec = new Vector3d(0,0,0);
		for(int i = -2; i<3; i++)
			for(int j = -1; j < 2; j++){
				disc.velocity = new Vector3d(14*Math.cos(i*Math.PI/6)*Math.cos(Math.PI/30), 14*Math.sin(i*Math.PI/6)*Math.cos(Math.PI/30), 14*Math.sin(Math.PI/30));
				((DiscMechanics)(disc.routine)).setCurvature(j*.05);
				catchPlayers = new HashSet<Player>(players);
				it = catchPlayers.iterator();
				while(it.hasNext()){
					temp = it.next();
					if(Math.hypot(temp.position.x - player.position.x, temp.position.y - player.position.y) <= 2)
						catchPlayers.remove(temp);
				}//End while
				test = Strategy.getClosestToDisc(disc, catchPlayers, player.team.field.dt);
				if(((Player)test[0]).team == player.team)
					if(player.team.endZone == Team.RIGHT){
						if(((Point3d)test[1]).x > ((Point3d)catcher[1]).x){
							vec = (Vector3d)(disc.velocity.clone());
							k = j*.05;
							catcher = test;
						}//End if
					}else if(((Point3d)test[1]).x < ((Point3d)catcher[1]).x){
						vec = (Vector3d)(disc.velocity.clone());
						k = j*.05;
						catcher = test;
					}//End if
			}//End for
		disc.velocity = vec;
		if(!vec.equals(new Vector3d(0, 0, 0))){
			((DiscMechanics)(disc.routine)).startThrow(k, Math.PI/30);
			player.setMovementRoutine(oldRoutine);
		}//End if
		return new Tuple3d[] {player.position, new Vector3d((player.team.endZone == Team.RIGHT)?1:-1,0,0)};
	}//End step()
	
	/** Sets the field to the input Field.
	 **/
	public void setField(Field field){
		this.field = field;
	}//End setField()
}//End ThrowingRoutine
